package com.yanqu.road.hs7;

import com.yanqu.road.define.YanQuMessageDefine;
import com.yanqu.road.message.YanQuMessage;
import com.yanqu.road.message.YanQuMessageBuffer;
import com.yanqu.road.server.protocol.ClientProtocol;
import com.yanqu.road.utils.ZipUtils;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageEncoder;
import io.netty.handler.codec.http.websocketx.WebSocketFrameEncoder;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.List;

public class YanQuWSEncrypt extends MessageToMessageEncoder<YanQuMessage> implements WebSocketFrameEncoder {

	private static Logger logger = LogManager.getLogger(YanQuWSEncrypt.class.getName());

	public YanQuWSEncrypt() {

	}

	@Override
	protected void encode(ChannelHandlerContext ctx, YanQuMessage msg, List<Object> out) throws Exception {
		if (msg.getMyMsg() instanceof YanQuMessageBuffer) {
			YanQuMessageBuffer messageBuffer = (YanQuMessageBuffer) msg.getMyMsg();
			for (YanQuMessage message : messageBuffer) {
				encode0(ctx, message, out);
			}
		} else {
			encode0(ctx, msg, out);
		}
	}

	private void encode0(ChannelHandlerContext ctx, YanQuMessage msg, List<Object> out) throws Exception {
		int dataSize = YanQuMessageDefine.HEADER_SIZE;
		if (msg.getBytes() != null) {
			if (msg.getCode() == ClientProtocol.U_ACTIVITY_LIST_ZIP || msg.getCode() == ClientProtocol.U_DAOMU_CONFIG_SYNC) {
				msg.setBytes(ZipUtils.gzip(msg.getBytes()));
			}
			dataSize += msg.getBytes().length;
		}

		boolean release = true;
		ByteBuf buf = null;
		try {
			if (dataSize <= YanQuMessageDefine.PACKAGE_SIZE_SMALL) {//小包体
				buf = encodeSmallPackage(ctx, msg, dataSize);
			} else if (dataSize <= YanQuMessageDefine.PACKAGE_SIZE_MIDDLE) {//中包体
				buf = encodeMiddlePackage(ctx, msg, dataSize);
			} else {//大包体
				buf = encodeBigPackage(ctx, msg, dataSize);
			}

			out.add(buf);

			release = false;
		} catch (Exception e) {
			logger.error("", e);
		} finally {
			if (release && buf != null) {
				buf.release();
			}
		}
	}

	private ByteBuf encodeBigPackage(ChannelHandlerContext ctx, YanQuMessage msg, int dataSize) {
		int size = 10 + dataSize;
		ByteBuf buf = ctx.alloc().buffer(size);
		buf.writeByte(130);
		buf.writeByte(127);
		buf.writeLong(dataSize);
		msg.writeHeaderByte(dataSize, buf);
		logger.info("big package of code = " + msg.getCode());
		return buf;
	}

	private ByteBuf encodeMiddlePackage(ChannelHandlerContext ctx, YanQuMessage msg, int dataSize) {
		int size = 4 + dataSize;
		ByteBuf buf = ctx.alloc().buffer(size);
		buf.writeByte(130);
		buf.writeByte(126);
		buf.writeByte(dataSize >>> 8 & 0xFF);
		buf.writeByte(dataSize & 0xFF);
		msg.writeHeaderByte(dataSize, buf);
		return buf;
	}

	private ByteBuf encodeSmallPackage(ChannelHandlerContext ctx, YanQuMessage msg, int dataSize) {
		int size = 2 + dataSize;
		ByteBuf buf = ctx.alloc().buffer(size);
		buf.writeByte(130);
		byte b = (byte) (dataSize);
		buf.writeByte(b);
		msg.writeHeaderByte(dataSize, buf);
		return buf;
	}

}
